import { I_graphToolbar, N_oFlowchart, Tsrv, ifs } from '../config';

class T_editor {
  // public nodeAttrs: any;

  // 编辑状态 新增按钮=new 修改按钮=modify 保存按钮=none
  private _editorState: string = `none`;

  public G_compID: string;

  public GT_compBox: ifs.I_compBox;

  // 选择的item
  private G_selectedItems: Array<any> = [];

  private _oFlowchart: any = undefined;

  private _graphToolbar: any = undefined;

  private _graph: any = undefined;

  private oldValue: any = null;

  // 注册的函数
  // 函数的统一注册格式  (obj: any) => Promise<boolean>
  // 按钮的函数命名方式 before_xxx do_xxx after_xxx
  // 内定的函数名 beforeHandleNodeAndEdge 新增、修改、删除节点或边前调用。
  private G_fns: Map<string, N_oFlowchart.TA_regFn> = new Map();

  constructor(compBoxInfo: ifs.I_compBoxInfo) {
    this.G_compID = compBoxInfo.compID;
    this.GT_compBox = compBoxInfo.TcompBox;
  }

  public get editorState(): string {
    return this._editorState;
  }

  public set editorState(s: string) {
    this._editorState = s;
    this.G_oFlowchart.onGraphEditorState(s); // 发送状态事件
  }

  public get G_oFlowchart(): any {
    if (!this._oFlowchart) {
      this._oFlowchart = this.GT_compBox.getCompMergeName(
        this.G_compID,
        `oFlowchart`
      );
    }
    return this._oFlowchart;
  }

  public get G_graph(): any {
    if (!this._graph) {
      this._graph = this.GT_compBox.getCompMergeName(this.G_compID, 'graph');
    }
    return this._graph;
  }

  public get GT_graphToolbar(): I_graphToolbar {
    if (!this._graphToolbar) {
      this._graphToolbar = this.GT_compBox.getCompMergeName(
        this.G_compID,
        `graphToolbar`
      );
    }
    return this._graphToolbar;
  }

  // 注册方法
  public regFn(reg: N_oFlowchart.I_regFn): void {
    this.G_fns.set(reg.name, reg.fn);
  }

  // 获取注册方法
  public getRegFn(name: string): N_oFlowchart.TA_regFn {
    return this.G_fns.get(name);
  }

  // 批量注册方法
  public regFns(fns: Array<N_oFlowchart.I_regFn>): void {
    fns.forEach(f => {
      this.regFn(f);
    });
  }

  public getGraph() {
    return this.G_graph;
  }

  // public on(event) {
  //   switch (event) {
  //     case 'graph_changeNodeData':
  //       this.G_graph.refresh();
  //       break;
  //     default:
  //   }
  // }

  // 增加元素
  public doAdd(type, item) {
    // g6 4.x 节点类型写法 type:nodeType
    item.type = item.shape;
    this.G_graph.addItem(type, item);
  }

  // 更新元素
  public doUpdate(item, model) {
    this.G_graph.updateItem(item, model);
  }

  // 删除元素
  public doRemove(item) {
    const node = this.G_graph.findById(item.id);
    this.G_graph.remove(node);
  }

  private doLayout(item) {}

  // 设置画面行为模式
  public setGraphMode(modeName: string) {
    this.G_graph.setMode(modeName);
  }

  public doSave(): object {
    return this.G_graph.save();
  }

  public saveOldValue() {
    this.oldValue = this.doSave();
  }

  public getOldValue() {
    return this.oldValue;
  }

  public restOldValue() {
    this.loadData(this.oldValue, true);
  }

  loadData(data: any, isFitView: boolean = false) {
    data && this.G_graph.read(data);
    isFitView && this.G_graph.fitView();
  }

  // 清除画布
  initGraph() {
    if (!this.G_graph) {
      return;
    }
    this.G_graph.clear();
    // this.GT_compBox.getCompMergeName(this.G_compID, `editor`).clearGraphStack();
    this.clearGraphStack();
  }

  public setEdgehoverStyles(edgeID: string, isShow: boolean) {
    const L_item = this.G_graph.findById(edgeID);
    L_item.setState('hover', isShow, L_item);
  }

  // -----------------------------------------command

  public initSelectedItems(items?: any) {
    const L_nodes = this.G_graph.findAllByState('node', 'selected');
    const L_edges = this.G_graph.findAllByState('edge', 'selected');
    this.G_selectedItems = L_nodes.concat(L_edges);
  }

  public getSelectedItems(): Array<any> {
    return this.G_selectedItems;
  }

  public cleanSelectedItems() {
    this.G_selectedItems = [];
  }

  public executeCommand(key: string, datas: Array<any>) {
    // 执行前检查
    if (this.G_fns.has('beforeHandleNodeAndEdge')) {
      this.G_fns.get('beforeHandleNodeAndEdge')({
        key,
        datas,
        graph: this.G_graph
      }).then(r => {
        !r && this.doHandleNodeAndEdge(key, datas);
      });
    } else {
      this.doHandleNodeAndEdge(key, datas);
    }
  }

  private doHandleNodeAndEdge(key: string, datas: Array<any>) {
    datas.forEach(data => {
      let model = data;
      switch (key) {
        case `add`:
          model.id = data.type + Tsrv.utils.custUUID(16, 16);
          break;
        case `addGroup`:
          model.groupId = data.type + Tsrv.utils.custUUID(16, 16);
          break;
        case `delete`:
          model = data.getModel();
          break;
        default:
      }
      this.doCommand(key, model);
    });
  }

  public doCommand(key: string, data: any) {
    switch (key) {
      case 'add':
        this.doAdd(data.type, data);

        break;
      case 'update':
        this.doUpdate(data.item, data.newModel);
        break;
      case 'delete':
        this.doRemove(data);
        break;
      case 'layout':
        this.doLayout(data);
        break;
      case 'addGroup':
        this.doAdd('group', data);
        break;
      default:
        throw new Error('有问题的key[editor.doCommand]');
    }
  }

  public clearGraphStack() {
    this.G_graph.clearStack();
    this.GT_graphToolbar.setBtnDisabled(`redo`, true);
    this.GT_graphToolbar.setBtnDisabled(`undo`, true);
  }

  public delete(item) {
    this.executeCommand('delete', [item]);
  }

  public cancelAllSelectItem() {
    let L_items = [];
    const L_nodes = this.G_graph.findAllByState('node', 'selected');
    const L_edges = this.G_graph.findAllByState('edge', 'selected');
    L_items = L_nodes.concat(L_edges);

    this.cleanSelectedItems();
    L_items.forEach(item => {
      item.setState('selected', false);
    });
  }

  // // 检查连线死循环 改为外部注册进来
  // private edgeEndlessLoopCheck(
  //   edges: any,
  //   beginNodeId: string, // 起始节点ID
  //   targetNodeId: string // 当前目标节点ID
  // ): boolean {
  //   const nextEdges = edges.filter(
  //     ele => ele.getModel().sourceId === targetNodeId
  //   );
  //   if (
  //     nextEdges.filter(item => item.getModel().targetId === beginNodeId)
  //       .length > 0
  //   ) {
  //     return true;
  //   }
  //   for (const element of nextEdges) {
  //     if (
  //       this.edgeEndlessLoopCheck(
  //         edges,
  //         beginNodeId,
  //         element.getModel().targetId
  //       )
  //     ) {
  //       return true;
  //     }
  //   }
  //   return false;
  // }

  // 连线规则应该从外注册进来，先写在这
  // private beforeExecCheck(key: string, datas: any): boolean {
  //   const L_graph = this.GT_compBox.getCompMergeName(this.G_compID,`graph`);
  //   const L_edgesNew = datas.filter(ele => ele.type === 'edge');
  //   const L_nodesNew = datas.filter(ele => ele.type === 'node');

  //   // 两节点间只能有一条连线并不能形成闭环;
  //   if (key === 'add' && datas.length > 0) {
  //     // 连线规则检查
  //     for (const element of L_edgesNew) {
  //       // 自己不能连接自己
  //       if (element.sourceId === element.targetId) {
  //         return true;
  //       }

  //       // // 当节点出口必须连接表达式接点
  //       // if (startAnchorPointName==='caseOut' && element.endAnchorPointName !== `exprIn`) {
  //       //   return true;
  //       // }

  //       const L_sourceNodeType = L_graph.findById(element.sourceId).getModel()
  //         .type;
  //       const L_edgesOld = L_graph.findAll('edge', edge => {
  //         const L_model = edge.getModel();
  //         // 重复连线
  //         if (
  //           L_model.sourceId === element.sourceId &&
  //           L_model.targetId === element.targetId
  //         ) {
  //           return true;
  //         }
  //         // 两节点闭环
  //         if (
  //           this.edgeEndlessLoopCheck(
  //             L_graph.getEdges(),
  //             element.sourceId,
  //             element.targetId
  //           )
  //         ) {
  //           return true;
  //         }
  //         // [当]节点除外,其它节点不允许出口有多条连线
  //         if (L_sourceNodeType !== 'caseNode') {
  //           if (
  //             L_model.sourceId === element.sourceId &&
  //             L_model.startAnchorPointName === element.startAnchorPointName
  //           ) {
  //             return true;
  //           }
  //         }
  //         return false;
  //       });
  //       if (L_edgesOld.length > 0) {
  //         return true;
  //       }
  //     }
  //     // 节点规则检查

  //     // 不允许有两个开始节点

  //     const L_beginNodes = L_nodesNew.filter(n => n.shape === 'beginNode');
  //     const L_nodesOld = L_graph.findAll('node', node => {
  //       return node.getModel().type === 'beginNode';
  //     });
  //     if (L_nodesOld.length > 0 && L_beginNodes.length > 0) {
  //       return true;
  //     }
  //   }
  //   return false;
  // }
}

export { T_editor };

export interface I_editor extends T_editor {}
